package com.fxkj.cloud.drms.application.impl;

import com.fxkj.cloud.dbs.common.constants.DeviceStatusEnum;
import com.fxkj.cloud.dbs.common.model.DeviceBasicInfo;
import com.fxkj.cloud.dbs.common.model.product.RelProductAttributeInfo;
import com.fxkj.cloud.drms.application.AlarmHistoryApplicationService;
import com.fxkj.cloud.drms.application.converter.AlarmHistoryApplicationConverter;
import com.fxkj.cloud.drms.application.model.vo.AlarmHistoryModelView;
import com.fxkj.cloud.drms.application.model.vo.ProductAlarmStatisticsModelView;
import com.fxkj.cloud.drms.domain.alarm.AlarmHistoryDomain;
import com.fxkj.cloud.drms.domain.alarm.AlarmStatistics;
import com.fxkj.cloud.drms.domain.alarm.service.AlarmHistoryDomainService;
import com.fxkj.cloud.drms.domain.device.repository.DeviceRepository;
import com.fxkj.cloud.drms.domain.product.ProductRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.web.PagedModel;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>description: </p>
 * @author ww
 * @date 2025/4/7 15:31
 */
@Component

public class AlarmHistoryApplicationServiceImpl implements AlarmHistoryApplicationService {
    private final Logger logger = LoggerFactory.getLogger(AlarmHistoryApplicationServiceImpl.class);
    private final AlarmHistoryDomainService alarmHistoryDomainService;
    private final AlarmHistoryApplicationConverter alarmHistoryApplicationConverter;
    private final DeviceRepository deviceRepository;
    private final ProductRepository productRepository;

    public AlarmHistoryApplicationServiceImpl(AlarmHistoryDomainService alarmHistoryDomainService,
                                              AlarmHistoryApplicationConverter alarmHistoryApplicationConverter,
                                              DeviceRepository deviceRepository, ProductRepository productRepository) {
        this.alarmHistoryDomainService = alarmHistoryDomainService;
        this.alarmHistoryApplicationConverter = alarmHistoryApplicationConverter;
        this.deviceRepository = deviceRepository;
        this.productRepository = productRepository;
    }

    @Override
    public PagedModel<AlarmHistoryModelView> list(Integer page, Integer size, UUID deviceId, UUID productId, UUID orgId, Integer alarmLevel, Long startTs, Long endTs, String alarmText, Boolean closed) {
        return new PagedModel<>(alarmHistoryDomainService.list(page, size, deviceId, productId, orgId, alarmLevel, startTs, endTs, alarmText, closed).map(alarmHistoryApplicationConverter::toModelView));
    }

    @Override
    public void create(String deviceSerialNo, Long ts, String alarmCode, String alarmText, String alarmValue) {
        DeviceBasicInfo deviceBasicInfo = deviceRepository.getDeviceBasicInfoByDeviceSerialNo(deviceSerialNo);
        if (null == deviceBasicInfo) {
            logger.trace("不存在的设备序列号:{}", deviceSerialNo);
            return;
        }
        RelProductAttributeInfo alarmInfo = productRepository.getAlarmAttributeName(deviceBasicInfo.getProductId(), alarmCode);
        if (null == alarmInfo) {
            logger.trace("不存在的告警编码:{}", alarmCode);
            return;
        }
        AlarmHistoryDomain alarmHistoryDomain = AlarmHistoryDomain.create(deviceSerialNo, deviceBasicInfo.getDeviceName(),
                ts, null, false, alarmText, alarmInfo.getAlarmLevel(), alarmCode, alarmValue,
                deviceBasicInfo.getDeviceId(), deviceBasicInfo.getProductId(), deviceBasicInfo.getOrganizationId(), alarmInfo.getAlarmName());
        alarmHistoryDomainService.save(alarmHistoryDomain);
        //告警开启状态
        deviceRepository.deviceStatusChange(deviceSerialNo, DeviceStatusEnum.ALARMING);
    }

    @Override
    public void close(String deviceSerialNo, Long ts, String alarmCode, String alarmText) {
        List<AlarmHistoryDomain> alarmHistoryDomains = alarmHistoryDomainService.findByDeviceSerialNoAndCodeAndClose(deviceSerialNo, alarmCode, false);
        long now = System.currentTimeMillis();
        alarmHistoryDomains.stream().forEach(alarmHistoryDomain -> {
            alarmHistoryDomain.close(now, alarmText);
        });
        alarmHistoryDomainService.saveAll(alarmHistoryDomains);
        //告警关闭状态变更
        deviceRepository.deviceStatusChange(deviceSerialNo, DeviceStatusEnum.ALARMING_STOP);
    }

    @Override
    public ProductAlarmStatisticsModelView productAlarmStatistics(UUID productId) {
        List<AlarmStatistics> alarmStatistics = alarmHistoryDomainService.productAlarmStatistics(Collections.singleton(productId));
        Map<Integer, AlarmStatistics> alarmStatisticsMap = alarmStatistics.stream().collect(Collectors.toMap(AlarmStatistics::getAlarmLevel, data -> data));
        return new ProductAlarmStatisticsModelView(
                alarmStatisticsMap.getOrDefault(1, AlarmStatistics.defaultNullStatistics()).getAlarmCount(),
                alarmStatisticsMap.getOrDefault(2, AlarmStatistics.defaultNullStatistics()).getAlarmCount(),
                alarmStatisticsMap.getOrDefault(3, AlarmStatistics.defaultNullStatistics()).getAlarmCount()
        );
    }

    @Override
    public ProductAlarmStatisticsModelView productModelAlarmStatistics(UUID productModelId) {
        Set<UUID> productIdsByModelId = productRepository.getProductIdsByModelId(productModelId);
        if (productIdsByModelId.isEmpty()) {
            return new ProductAlarmStatisticsModelView(0L, 0L, 0L);
        }
        List<AlarmStatistics> alarmStatistics = alarmHistoryDomainService.productAlarmStatistics(productIdsByModelId);
        Map<Integer, AlarmStatistics> alarmStatisticsMap = alarmStatistics.stream().collect(Collectors.toMap(AlarmStatistics::getAlarmLevel, data -> data));
        return new ProductAlarmStatisticsModelView(
                alarmStatisticsMap.getOrDefault(1, AlarmStatistics.defaultNullStatistics()).getAlarmCount(),
                alarmStatisticsMap.getOrDefault(2, AlarmStatistics.defaultNullStatistics()).getAlarmCount(),
                alarmStatisticsMap.getOrDefault(3, AlarmStatistics.defaultNullStatistics()).getAlarmCount()
        );
    }
}
